#include "imgui/node/Panel.h"
#include <cmath>

using namespace ImNodes;

void ImNodes::Panel::Tick()
{
    ImGuiIO &io = ImGui::GetIO();

    ImGui::PushID(this);

    ImNodes::BeginNodeEditor();

    EditAllNodes();

    InstAllLinks();

    OnContextWindow();

    ImNodes::EndNodeEditor();

    EditNodeFirstFrame();

    OnCreateLink();

    OnDelete();

    TickAllNodes();

    ImGui::PopID();
};

void ImNodes::Panel::InitColors()
{

    Colors redColors[8] = {
        { ImColor::HSV(0.0f, 0.5f, 0.5f), ImColor::HSV(0.0f, 0.4f, 0.5f), ImColor::HSV(0.0f, 0.5f, 0.4f) },
        { ImColor::HSV(0.0f, 0.6f, 0.6f), ImColor::HSV(0.0f, 0.48f, 0.6f), ImColor::HSV(0.0f, 0.6f, 0.48f) },
        { ImColor::HSV(0.0f, 0.7f, 0.7f), ImColor::HSV(0.0f, 0.56f, 0.7f), ImColor::HSV(0.0f, 0.7f, 0.56f) },
        { ImColor::HSV(0.0f, 0.8f, 0.8f), ImColor::HSV(0.0f, 0.64f, 0.8f), ImColor::HSV(0.0f, 0.8f, 0.64f) },
        { ImColor::HSV(0.0f, 0.9f, 0.9f), ImColor::HSV(0.0f, 0.72f, 0.9f), ImColor::HSV(0.0f, 0.9f, 0.72f) },
        { ImColor::HSV(0.0f, 1.0f, 1.0f), ImColor::HSV(0.0f, 0.8f, 1.0f), ImColor::HSV(0.0f, 1.0f, 0.8f) },
        { ImColor::HSV(0.0f, 1.0f, 0.8f), ImColor::HSV(0.0f, 0.8f, 0.8f), ImColor::HSV(0.0f, 1.0f, 0.6f) },
        { ImColor::HSV(0.0f, 0.9f, 0.6f), ImColor::HSV(0.0f, 0.72f, 0.6f), ImColor::HSV(0.0f, 0.9f, 0.5f) }
    };

    Colors greenColors[8] = {
        { ImColor::HSV(120.0f / 360.0f, 0.5f, 0.5f), ImColor::HSV(120.0f / 360.0f, 0.4f, 0.5f), ImColor::HSV(120.0f / 360.0f, 0.5f, 0.4f) },
        { ImColor::HSV(120.0f / 360.0f, 0.6f, 0.6f), ImColor::HSV(120.0f / 360.0f, 0.48f, 0.6f), ImColor::HSV(120.0f / 360.0f, 0.6f, 0.48f) },
        { ImColor::HSV(120.0f / 360.0f, 0.7f, 0.7f), ImColor::HSV(120.0f / 360.0f, 0.56f, 0.7f), ImColor::HSV(120.0f / 360.0f, 0.7f, 0.56f) },
        { ImColor::HSV(120.0f / 360.0f, 0.8f, 0.8f), ImColor::HSV(120.0f / 360.0f, 0.64f, 0.8f), ImColor::HSV(120.0f / 360.0f, 0.8f, 0.64f) },
        { ImColor::HSV(120.0f / 360.0f, 0.9f, 0.9f), ImColor::HSV(120.0f / 360.0f, 0.72f, 0.9f), ImColor::HSV(120.0f / 360.0f, 0.9f, 0.72f) },
        { ImColor::HSV(120.0f / 360.0f, 1.0f, 1.0f), ImColor::HSV(120.0f / 360.0f, 0.8f, 1.0f), ImColor::HSV(120.0f / 360.0f, 1.0f, 0.8f) },
        { ImColor::HSV(120.0f / 360.0f, 1.0f, 0.8f), ImColor::HSV(120.0f / 360.0f, 0.8f, 0.8f), ImColor::HSV(120.0f / 360.0f, 1.0f, 0.6f) },
        { ImColor::HSV(120.0f / 360.0f, 0.9f, 0.6f), ImColor::HSV(120.0f / 360.0f, 0.72f, 0.6f), ImColor::HSV(120.0f / 360.0f, 0.9f, 0.5f) }
    };

    Colors blueColors[8] = {
        { ImColor::HSV(240.0f / 360.0f, 0.5f, 0.5f), ImColor::HSV(240.0f / 360.0f, 0.4f, 0.5f), ImColor::HSV(240.0f / 360.0f, 0.5f, 0.4f) },
        { ImColor::HSV(240.0f / 360.0f, 0.6f, 0.6f), ImColor::HSV(240.0f / 360.0f, 0.48f, 0.6f), ImColor::HSV(240.0f / 360.0f, 0.6f, 0.48f) },
        { ImColor::HSV(240.0f / 360.0f, 0.7f, 0.7f), ImColor::HSV(240.0f / 360.0f, 0.56f, 0.7f), ImColor::HSV(240.0f / 360.0f, 0.7f, 0.56f) },
        { ImColor::HSV(240.0f / 360.0f, 0.8f, 0.8f), ImColor::HSV(240.0f / 360.0f, 0.64f, 0.8f), ImColor::HSV(240.0f / 360.0f, 0.8f, 0.64f) },
        { ImColor::HSV(240.0f / 360.0f, 0.9f, 0.9f), ImColor::HSV(240.0f / 360.0f, 0.72f, 0.9f), ImColor::HSV(240.0f / 360.0f, 0.9f, 0.72f) },
        { ImColor::HSV(240.0f / 360.0f, 1.0f, 1.0f), ImColor::HSV(240.0f / 360.0f, 0.8f, 1.0f), ImColor::HSV(240.0f / 360.0f, 1.0f, 0.8f) },
        { ImColor::HSV(240.0f / 360.0f, 1.0f, 0.8f), ImColor::HSV(240.0f / 360.0f, 0.8f, 0.8f), ImColor::HSV(240.0f / 360.0f, 1.0f, 0.6f) },
        { ImColor::HSV(240.0f / 360.0f, 0.9f, 0.6f), ImColor::HSV(240.0f / 360.0f, 0.72f, 0.6f), ImColor::HSV(240.0f / 360.0f, 0.9f, 0.5f) }
    };

    Colors yellowColors[8] = {
        { ImColor::HSV(60.0f / 360.0f, 0.5f, 0.5f), ImColor::HSV(60.0f / 360.0f, 0.4f, 0.5f), ImColor::HSV(60.0f / 360.0f, 0.5f, 0.4f) },
        { ImColor::HSV(60.0f / 360.0f, 0.6f, 0.6f), ImColor::HSV(60.0f / 360.0f, 0.48f, 0.6f), ImColor::HSV(60.0f / 360.0f, 0.6f, 0.48f) },
        { ImColor::HSV(60.0f / 360.0f, 0.7f, 0.7f), ImColor::HSV(60.0f / 360.0f, 0.56f, 0.7f), ImColor::HSV(60.0f / 360.0f, 0.7f, 0.56f) },
        { ImColor::HSV(60.0f / 360.0f, 0.8f, 0.8f), ImColor::HSV(60.0f / 360.0f, 0.64f, 0.8f), ImColor::HSV(60.0f / 360.0f, 0.8f, 0.64f) },
        { ImColor::HSV(60.0f / 360.0f, 0.9f, 0.9f), ImColor::HSV(60.0f / 360.0f, 0.72f, 0.9f), ImColor::HSV(60.0f / 360.0f, 0.9f, 0.72f) },
        { ImColor::HSV(60.0f / 360.0f, 1.0f, 1.0f), ImColor::HSV(60.0f / 360.0f, 0.8f, 1.0f), ImColor::HSV(60.0f / 360.0f, 1.0f, 0.8f) },
        { ImColor::HSV(60.0f / 360.0f, 1.0f, 0.8f), ImColor::HSV(60.0f / 360.0f, 0.8f, 0.8f), ImColor::HSV(60.0f / 360.0f, 1.0f, 0.6f) },
        { ImColor::HSV(60.0f / 360.0f, 0.9f, 0.6f), ImColor::HSV(60.0f / 360.0f, 0.72f, 0.6f), ImColor::HSV(60.0f / 360.0f, 0.9f, 0.5f) }
    };
    for (int i = 0; i < 8; i++)
    {
        m_Colors[i * 4 + 0] = redColors[i];
        m_Colors[i * 4 + 1] = blueColors[i];
        m_Colors[i * 4 + 2] = greenColors[i];
        m_Colors[i * 4 + 3] = yellowColors[i];
    }

};

bool ImNodes::Panel::CreateLink(int startId, int endId)
{
    if (TryLink<IntPin>(m_IntPins, m_IntLinks, startId, endId))
    {
        return true;
    }

    if (TryLink<FloatPin>(m_FloatPins, m_FloatLinks, startId, endId))
    {
        return true;
    }

    if (TryLink<StringPin>(m_StringPins, m_StringLinks, startId, endId))
    {
        return true;
    }

    return false;
};

void ImNodes::Panel::OnCreateLink()
{
    int startId;
    int endId;

    if (ImNodes::IsLinkCreated(&startId, &endId))
    {
        bool createLinkflag = CreateLink(startId, endId);
        if (createLinkflag)
        {
            std::cout << "Create link" << std::endl;
        }
    };
};

void ImNodes::Panel::OnDelete()
{
    // delete links and nodes;
    if (ImGui::IsKeyReleased(ImGuiKey_Delete)) {

        std::vector<int> links;
        std::vector<int> nodes;

        // Delete add links selected
        int numSelectLinks = ImNodes::NumSelectedLinks();
        if (numSelectLinks)
        {
            links.resize(numSelectLinks);
            ImNodes::GetSelectedLinks(links.data());

        }

        // Delete all nodes

        int numSelectNodes = ImNodes::NumSelectedNodes();
        if (numSelectNodes)
        {
            nodes.resize(numSelectNodes);
            ImNodes::GetSelectedNodes(nodes.data());

            for (auto nodeId : nodes)
            {
                for (auto linkIt : m_Links)
                {
                    bool linkRelateNode = this->LinkRelatedNode(linkIt.first, nodeId);
                    if (linkRelateNode)
                    {
                        links.push_back(linkIt.first);
                    }
                }
            }
        }

        for (auto it : links)
        {
            this->SetLinkEnable(it, false);
        }
        for (auto it : nodes)
        {
            this->SetNodeEnable(it, false);
        }
    }
};

template <>
void ImNodes::Panel::RegisterPin<ImNodes::StringPin>(std::shared_ptr<ImNodes::StringPin> pin)
{
    m_Pins[pin->m_Id] = pin;
    m_StringPins[pin->m_Id] = pin;
};

template <>
void ImNodes::Panel::RegisterPin<ImNodes::FloatPin>(std::shared_ptr<ImNodes::FloatPin> pin)
{
    m_Pins[pin->m_Id] = pin;
    m_FloatPins[pin->m_Id] = pin;
};

template<>
void ImNodes::Panel::RegisterPin<ImNodes::IntPin>(std::shared_ptr<ImNodes::IntPin> pin)
{
    m_Pins[pin->m_Id] = pin;
    m_IntPins[pin->m_Id] = pin;


}
